home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / MOR55SRC.ZIP / MORIA / SOURCE / SAVE.C < prev    next >
C/C++ Source or Header  |  1992-12-07  |  42KB  |  1,641 lines

  1. /* source/save.c: save and restore games and monster memory info
  2.  
  3.    Copyright (c) 1989-92 James E. Wilson, Robert A. Koeneke
  4.  
  5.    This software may be copied and distributed for educational, research, and
  6.    not for profit purposes provided that this copyright and statement are
  7.    included in all such copies. */
  8.  
  9. /* For debugging the savefile code on systems with broken compilers.  */
  10. #if 0
  11. #define DEBUG(x)    x
  12. #else
  13. #define DEBUG(x)
  14. #endif
  15.  
  16. #include <stdio.h>
  17.  
  18. #ifndef STDIO_LOADED
  19. #define STDIO_LOADED
  20. #endif
  21.  
  22. #ifdef __TURBOC__
  23. #include    <io.h>
  24. #endif /* __TURBOC__ */
  25.  
  26. #include "config.h"
  27. #include "constant.h"
  28. #include "types.h"
  29.  
  30. #ifndef USG
  31. /* stuff only needed for Berkeley UNIX */
  32. #include <sys/types.h>
  33. #include <sys/file.h>
  34. #include <sys/param.h>
  35. #endif
  36.  
  37. #ifdef VMS
  38. #include <string.h>
  39. #include <file.h>
  40. #else
  41. #ifdef USG
  42. #ifndef ATARIST_MWC
  43. #include <string.h>
  44. #ifndef ATARIST_TC
  45. #include <fcntl.h>
  46. #endif
  47. #else
  48. #include "string.h"
  49. #endif
  50. #else
  51. #include <strings.h>
  52. #endif
  53. #endif
  54.  
  55. /* This must be included after fcntl.h, which has a prototype for `open'
  56.    on some systems.  Otherwise, the `open' prototype conflicts with the
  57.    `topen' declaration.  */
  58. #include "externs.h"
  59.  
  60. #ifdef ATARIST_TC
  61. #include <time.h>
  62. #endif
  63.  
  64. DEBUG(static FILE *logfile);
  65.  
  66. #if defined(LINT_ARGS)
  67. static int sv_write(void);
  68. static void wr_byte(int8u);
  69. static void wr_short(int16u);
  70. static void wr_long(int32u);
  71. static void wr_bytes(int8u *, int);
  72. static void wr_string(char *);
  73. static void wr_shorts(int16u *, int);
  74. static void wr_item(inven_type *);
  75. static void wr_monster(monster_type *);
  76. static void rd_byte(int8u *);
  77. static void rd_short(int16u *);
  78. static void rd_long(int32u *);
  79. static void rd_bytes(int8u *, int);
  80. static void rd_string(char *);
  81. static void rd_shorts(int16u *, int);
  82. static void rd_item(inven_type *);
  83. static void rd_monster(monster_type *);
  84. #else
  85. static int sv_write();
  86. static void wr_byte();
  87. static void wr_short();
  88. static void wr_long();
  89. static void wr_bytes();
  90. static void wr_string();
  91. static void wr_shorts();
  92. static void wr_item();
  93. static void wr_monster();
  94. static void rd_byte();
  95. static void rd_short();
  96. static void rd_long();
  97. static void rd_bytes();
  98. static void rd_string();
  99. static void rd_shorts();
  100. static void rd_item();
  101. static void rd_monster();
  102. #endif
  103.  
  104. #if !defined(ATARIST_MWC)
  105. #ifdef MAC
  106. #include <time.h>
  107. #else
  108. long time();
  109. #endif
  110. #else
  111. char *malloc();
  112. #endif
  113.  
  114. /* these are used for the save file, to avoid having to pass them to every
  115.    procedure */
  116. static FILE *fileptr;
  117. static int8u xor_byte;
  118. static int from_savefile;    /* can overwrite old savefile when save */
  119. static int32u start_time;    /* time that play started */
  120.  
  121. /* This save package was brought to by            -JWT-
  122.    and                            -RAK-
  123.    and has been completely rewritten for UNIX by    -JEW-  */
  124. /* and has been completely rewritten again by     -CJS-    */
  125. /* and completely rewritten again! for portability by -JEW- */
  126.  
  127. static int sv_write()
  128. {
  129.   int32u l;
  130.   register int i, j;
  131.   int count;
  132.   int8u char_tmp, prev_char;
  133.   register cave_type *c_ptr;
  134.   register recall_type *r_ptr;
  135.   struct stats *s_ptr;
  136.   register struct flags *f_ptr;
  137.   store_type *st_ptr;
  138.   struct misc *m_ptr;
  139. #if defined(MSDOS) || defined(ATARI_ST)
  140.   inven_type *t_ptr;
  141. #endif
  142.  
  143.   /* clear the death flag when creating a HANGUP save file, so that player
  144.      can see tombstone when restart */
  145.   if (eof_flag)
  146.     death = FALSE;
  147.  
  148.   l = 0;
  149.   if (find_cut)
  150.     l |= 0x1;
  151.   if (find_examine)
  152.     l |= 0x2;
  153.   if (find_prself)
  154.     l |= 0x4;
  155.   if (find_bound)
  156.     l |= 0x8;
  157.   if (prompt_carry_flag)
  158.     l |= 0x10;
  159.   if (rogue_like_commands)
  160.     l |= 0x20;
  161.   if (show_weight_flag)
  162.     l |= 0x40;
  163.   if (highlight_seams)
  164.     l |= 0x80;
  165.   if (find_ignore_doors)
  166.     l |= 0x100;
  167.   if (sound_beep_flag)
  168.     l |= 0x200;
  169.   if (display_counts)
  170.     l |= 0x400;
  171.   if (death)
  172.     l |= 0x80000000L;    /* Sign bit */
  173.   if (total_winner)
  174.     l |= 0x40000000L;
  175.  
  176.   for (i = 0; i < MAX_CREATURES; i++)
  177.     {
  178.       r_ptr = &c_recall[i];
  179.       if (r_ptr->r_cmove || r_ptr->r_cdefense || r_ptr->r_kills ||
  180.       r_ptr->r_spells || r_ptr->r_deaths || r_ptr->r_attacks[0] ||
  181.       r_ptr->r_attacks[1] || r_ptr->r_attacks[2] || r_ptr->r_attacks[3])
  182.     {
  183.       wr_short((int16u)i);
  184.       wr_long(r_ptr->r_cmove);
  185.       wr_long(r_ptr->r_spells);
  186.       wr_short(r_ptr->r_kills);
  187.       wr_short(r_ptr->r_deaths);
  188.       wr_short(r_ptr->r_cdefense);
  189.       wr_byte(r_ptr->r_wake);
  190.       wr_byte(r_ptr->r_ignore);
  191.       wr_bytes(r_ptr->r_attacks, MAX_MON_NATTACK);
  192.     }
  193.     }
  194.   wr_short((int16u)0xFFFF); /* sentinel to indicate no more monster info */
  195.  
  196.   wr_long(l);
  197.  
  198.   m_ptr = &py.misc;
  199.   wr_string(m_ptr->name);
  200.   wr_byte(m_ptr->male);
  201.   wr_long((int32u)m_ptr->au);
  202.   wr_long((int32u)m_ptr->max_exp);
  203.   wr_long((int32u)m_ptr->exp);
  204.   wr_short(m_ptr->exp_frac);
  205.   wr_short(m_ptr->age);
  206.   wr_short(m_ptr->ht);
  207.   wr_short(m_ptr->wt);
  208.   wr_short(m_ptr->lev);
  209.   wr_short(m_ptr->max_dlv);
  210.   wr_short((int16u)m_ptr->srh);
  211.   wr_short((int16u)m_ptr->fos);
  212.   wr_short((int16u)m_ptr->bth);
  213.   wr_short((int16u)m_ptr->bthb);
  214.   wr_short((int16u)m_ptr->mana);
  215.   wr_short((int16u)m_ptr->mhp);
  216.   wr_short((int16u)m_ptr->ptohit);
  217.   wr_short((int16u)m_ptr->ptodam);
  218.   wr_short((int16u)m_ptr->pac);
  219.   wr_short((int16u)m_ptr->ptoac);
  220.   wr_short((int16u)m_ptr->dis_th);
  221.   wr_short((int16u)m_ptr->dis_td);
  222.   wr_short((int16u)m_ptr->dis_ac);
  223.   wr_short((int16u)m_ptr->dis_tac);
  224.   wr_short((int16u)m_ptr->disarm);
  225.   wr_short((int16u)m_ptr->save);
  226.   wr_short((int16u)m_ptr->sc);
  227.   wr_short((int16u)m_ptr->stl);
  228.   wr_byte(m_ptr->pclass);
  229.   wr_byte(m_ptr->prace);
  230.   wr_byte(m_ptr->hitdie);
  231.   wr_byte(m_ptr->expfact);
  232.   wr_short((int16u)m_ptr->cmana);
  233.   wr_short(m_ptr->cmana_frac);
  234.   wr_short((int16u)m_ptr->chp);
  235.   wr_short(m_ptr->chp_frac);
  236.   for (i = 0; i < 4; i++)
  237.     wr_string (m_ptr->history[i]);
  238.  
  239.   s_ptr = &py.stats;
  240.   wr_bytes(s_ptr->max_stat, 6);
  241.   wr_bytes(s_ptr->cur_stat, 6);
  242.   wr_shorts((int16u *)s_ptr->mod_stat, 6);
  243.   wr_bytes(s_ptr->use_stat, 6);
  244.  
  245.   f_ptr = &py.flags;
  246.   wr_long(f_ptr->status);
  247.   wr_short((int16u)f_ptr->rest);
  248.   wr_short((int16u)f_ptr->blind);
  249.   wr_short((int16u)f_ptr->paralysis);
  250.   wr_short((int16u)f_ptr->confused);
  251.   wr_short((int16u)f_ptr->food);
  252.   wr_short((int16u)f_ptr->food_digested);
  253.   wr_short((int16u)f_ptr->protection);
  254.   wr_short((int16u)f_ptr->speed);
  255.   wr_short((int16u)f_ptr->fast);
  256.   wr_short((int16u)f_ptr->slow);
  257.   wr_short((int16u)f_ptr->afraid);
  258.   wr_short((int16u)f_ptr->poisoned);
  259.   wr_short((int16u)f_ptr->image);
  260.   wr_short((int16u)f_ptr->protevil);
  261.   wr_short((int16u)f_ptr->invuln);
  262.   wr_short((int16u)f_ptr->hero);
  263.   wr_short((int16u)f_ptr->shero);
  264.   wr_short((int16u)f_ptr->blessed);
  265.   wr_short((int16u)f_ptr->resist_heat);
  266.   wr_short((int16u)f_ptr->resist_cold);
  267.   wr_short((int16u)f_ptr->detect_inv);
  268.   wr_short((int16u)f_ptr->word_recall);
  269.   wr_short((int16u)f_ptr->see_infra);
  270.   wr_short((int16u)f_ptr->tim_infra);
  271.   wr_byte(f_ptr->see_inv);
  272.   wr_byte(f_ptr->teleport);
  273.   wr_byte(f_ptr->free_act);
  274.   wr_byte(f_ptr->slow_digest);
  275.   wr_byte(f_ptr->aggravate);
  276.   wr_byte(f_ptr->fire_resist);
  277.   wr_byte(f_ptr->cold_resist);
  278.   wr_byte(f_ptr->acid_resist);
  279.   wr_byte(f_ptr->regenerate);
  280.   wr_byte(f_ptr->lght_resist);
  281.   wr_byte(f_ptr->ffall);
  282.   wr_byte(f_ptr->sustain_str);
  283.   wr_byte(f_ptr->sustain_int);
  284.   wr_byte(f_ptr->sustain_wis);
  285.   wr_byte(f_ptr->sustain_con);
  286.   wr_byte(f_ptr->sustain_dex);
  287.   wr_byte(f_ptr->sustain_chr);
  288.   wr_byte(f_ptr->confuse_monster);
  289.   wr_byte(f_ptr->new_spells);
  290.  
  291.   wr_short((int16u)missile_ctr);
  292.   wr_long((int32u)turn);
  293.   wr_short((int16u)inven_ctr);
  294.   for (i = 0; i < inven_ctr; i++)
  295.     wr_item(&inventory[i]);
  296.   for (i = INVEN_WIELD; i < INVEN_ARRAY_SIZE; i++)
  297.     wr_item(&inventory[i]);
  298.   wr_short((int16u)inven_weight);
  299.   wr_short((int16u)equip_ctr);
  300.   wr_long(spell_learned);
  301.   wr_long(spell_worked);
  302.   wr_long(spell_forgotten);
  303.   wr_bytes(spell_order, 32);
  304.   wr_bytes(object_ident, OBJECT_IDENT_SIZE);
  305.   wr_long(randes_seed);
  306.   wr_long(town_seed);
  307.   wr_short((int16u)last_msg);
  308.   for (i = 0; i < MAX_SAVE_MSG; i++)
  309.     wr_string(old_msg[i]);
  310.  
  311.   /* this indicates 'cheating' if it is a one */
  312.   wr_short((int16u)panic_save);
  313.   wr_short((int16u)total_winner);
  314.   wr_short((int16u)noscore);
  315.   wr_shorts(player_hp, MAX_PLAYER_LEVEL);
  316.  
  317.   for (i = 0; i < MAX_STORES; i++)
  318.     {
  319.       st_ptr = &store[i];
  320.       wr_long((int32u)st_ptr->store_open);
  321.       wr_short((int16u)st_ptr->insult_cur);
  322.       wr_byte(st_ptr->owner);
  323.       wr_byte(st_ptr->store_ctr);
  324.       wr_short(st_ptr->good_buy);
  325.       wr_short(st_ptr->bad_buy);
  326.       for (j = 0; j < st_ptr->store_ctr; j++)
  327.     {
  328.       wr_long((int32u)st_ptr->store_inven[j].scost);
  329.       wr_item(&st_ptr->store_inven[j].sitem);
  330.     }
  331.     }
  332.  
  333.   /* save the current time in the savefile */
  334. #ifdef MAC
  335.   l = time((time_t *)0);
  336. #else
  337.   l = time((long *)0);
  338. #endif
  339.   if (l < start_time)
  340.     {
  341.       /* someone is messing with the clock!, assume that we have been
  342.      playing for 1 day */
  343.       l = start_time + 86400L;
  344.     }
  345.   wr_long(l);
  346.  
  347.   /* starting with 5.2, put died_from string in savefile */
  348.   wr_string(died_from);
  349.  
  350.   /* starting with 5.2.2, put the max_score in the savefile */
  351.   l = total_points ();
  352.   wr_long (l);
  353.  
  354.   /* starting with 5.2.2, put the birth_date in the savefile */
  355.   wr_long ((int32u) birth_date);
  356.  
  357.   /* only level specific info follows, this allows characters to be
  358.      resurrected, the dungeon level info is not needed for a resurrection */
  359.   if (death)
  360.     {
  361.       if (ferror(fileptr) || fflush(fileptr) == EOF)
  362.     return FALSE;
  363.       return TRUE;
  364.     }
  365.  
  366.   wr_short((int16u)dun_level);
  367.   wr_short((int16u)char_row);
  368.   wr_short((int16u)char_col);
  369.   wr_short((int16u)mon_tot_mult);
  370.   wr_short((int16u)cur_height);
  371.   wr_short((int16u)cur_width);
  372.   wr_short((int16u)max_panel_rows);
  373.   wr_short((int16u)max_panel_cols);
  374.  
  375.   for (i = 0; i < MAX_HEIGHT; i++)
  376.     for (j = 0; j < MAX_WIDTH; j++)
  377.       {
  378.     c_ptr = &cave[i][j];
  379.     if (c_ptr->cptr != 0)
  380.       {
  381.         wr_byte((int8u)i);
  382.         wr_byte((int8u)j);
  383.         wr_byte(c_ptr->cptr);
  384.       }
  385.       }
  386.   wr_byte((int8u)0xFF); /* marks end of cptr info */
  387.   for (i = 0; i < MAX_HEIGHT; i++)
  388.     for (j = 0; j < MAX_WIDTH; j++)
  389.       {
  390.     c_ptr = &cave[i][j];
  391.     if (c_ptr->tptr != 0)
  392.       {
  393.         wr_byte((int8u)i);
  394.         wr_byte((int8u)j);
  395.         wr_byte(c_ptr->tptr);
  396.       }
  397.       }
  398.   wr_byte((int8u)0xFF); /* marks end of tptr info */
  399.   /* must set counter to zero, note that code may write out two bytes
  400.      unnecessarily */
  401.   count = 0;
  402.   prev_char = 0;
  403.   for (i = 0; i < MAX_HEIGHT; i++)
  404.     for (j = 0; j < MAX_WIDTH; j++)
  405.       {
  406.     c_ptr = &cave[i][j];
  407.     char_tmp = c_ptr->fval | (c_ptr->lr << 4) | (c_ptr->fm << 5) |
  408.       (c_ptr->pl << 6) | (c_ptr->tl << 7);
  409.     if (char_tmp != prev_char || count == MAX_UCHAR)
  410.       {
  411.         wr_byte((int8u)count);
  412.         wr_byte(prev_char);
  413.         prev_char = char_tmp;
  414.         count = 1;
  415.       }
  416.     else
  417.       count++;
  418.       }
  419.   /* save last entry */
  420.   wr_byte((int8u)count);
  421.   wr_byte(prev_char);
  422.  
  423. #if defined(MSDOS) || defined(ATARI_ST)
  424.   /* must change graphics symbols for walls and floors back to default chars,
  425.      this is necessary so that if the user changes the graphics line, the
  426.      program will be able change all existing walls and floors to the new
  427.      symbol */
  428.   /* Or if the user moves the savefile from one machine to another, we
  429.      must have a consistent representation here.  */
  430.   t_ptr = &t_list[tcptr - 1];
  431.   for (i = tcptr - 1; i >= MIN_TRIX; i--)
  432.     {
  433. #ifdef MSDOS
  434.       if (t_ptr->tchar == wallsym)
  435.     t_ptr->tchar = '#';
  436. #endif
  437. #ifdef ATARI_ST
  438.       if (t_ptr->tchar == (unsigned char)240)
  439.     t_ptr->tchar = '#';
  440. #endif
  441.       t_ptr--;
  442.     }
  443. #endif
  444.   wr_short((int16u)tcptr);
  445.   for (i = MIN_TRIX; i < tcptr; i++)
  446.     wr_item(&t_list[i]);
  447.   wr_short((int16u)mfptr);
  448.   for (i = MIN_MONIX; i < mfptr; i++)
  449.     wr_monster(&m_list[i]);
  450.  
  451.   if (ferror(fileptr) || (fflush(fileptr) == EOF))
  452.     return FALSE;
  453.   return TRUE;
  454. }
  455.  
  456. #ifdef MAC
  457.  
  458. /* Set up prior to actual save, do the save, then clean up */
  459. /* Notice that Mac version of this function takes a parameter */
  460. /* To do a "save as" set always_ask */
  461. /* To do a "save" clear always_ask */
  462.  
  463. int save_char(always_ask)
  464. int always_ask;
  465. {
  466.   int rc, already_set, proceed;
  467.   int16 vrefnum;
  468.  
  469.   /* cannot rely on _save_char to do this because we may put up a dialog */
  470.   if (character_saved) return(TRUE);
  471.  
  472.   enablefilemenu(FALSE);
  473.  
  474.   already_set = getsavedefaults(savefile, &vrefnum);
  475.  
  476.   if (!already_set || always_ask)
  477.     {
  478.       /* Here if always_ask or user has not yet specified a save file */
  479.       /* User specifies a save file when he restarts a previous one */
  480.       sfposition(vrefnum);
  481.       proceed = doputfile(death ? "Save memories as:" : "Save game as:",
  482.               savefile, &vrefnum);
  483.     }
  484.   else
  485.     proceed = TRUE;
  486.  
  487.   if (proceed)
  488.     {
  489.       changedirectory(vrefnum);
  490.       rc = _save_char(savefile);
  491.       restoredirectory();
  492.     }
  493.   else
  494.     rc = FALSE;
  495.  
  496.   if (rc)
  497.     (void) setfileinfo(savefile, vrefnum, SAVE_FTYPE);
  498.  
  499.   enablefilemenu(TRUE);
  500.  
  501.   return(rc);
  502. }
  503.  
  504. #else
  505.  
  506. /* The Mac has different logic here -- See above */
  507.  
  508. int save_char()
  509. {
  510.   int i;
  511.   vtype temp;
  512.  
  513. #ifdef SECURE
  514.   bePlayer();
  515. #endif
  516.  
  517.   while (!_save_char(savefile))
  518.     {
  519.       (void) sprintf(temp, "Savefile '%s' fails.", savefile);
  520.       msg_print(temp);
  521.       i = 0;
  522.       if (access(savefile, 0) < 0
  523.       || get_check("File exists. Delete old savefile?") == 0
  524.       || (i = unlink(savefile)) < 0)
  525.     {
  526.       if (i < 0)
  527.         {
  528.           (void) sprintf(temp, "Can't delete '%s'", savefile);
  529.           msg_print(temp);
  530.         }
  531.       prt("New Savefile [ESC to give up]:", 0, 0);
  532.       if (!get_string(temp, 0, 31, 45))
  533.         return FALSE;
  534.       if (temp[0])
  535.         (void) strcpy(savefile, temp);
  536.     }
  537.       (void) sprintf(temp, "Saving with %s...", savefile);
  538.       prt(temp, 0, 0);
  539.     }
  540. #ifdef SECURE
  541.   beGames();
  542. #endif
  543.   return TRUE;
  544. }
  545. #endif
  546.  
  547. int _save_char(fnam)
  548. char *fnam;
  549. {
  550.   vtype temp;
  551.   register int ok, fd;
  552.   int8u char_tmp;
  553.  
  554.   if (character_saved)
  555.     return TRUE;    /* Nothing to save. */
  556.  
  557.   nosignals();
  558.   put_qio();
  559.   disturb (1, 0);        /* Turn off resting and searching. */
  560.   change_speed(-pack_heavy);    /* Fix the speed */
  561.   pack_heavy = 0;
  562.   ok = FALSE;
  563.   /* VMS files have version numbers, so don't worry about overwriting
  564.      the old save file. */
  565. #if !defined(ATARIST_MWC) && !defined(VMS)
  566.   fd = -1;
  567.   fileptr = NULL;        /* Do not assume it has been init'ed */
  568. #if defined(MAC) || defined(AMIGA)
  569.   /* The Mac version automatically overwrites */
  570.   fd = open(fnam, O_RDWR|O_CREAT|O_TRUNC);
  571. #ifdef MAC
  572.   macbeginwait ();
  573. #endif
  574. #else
  575.   fd = open(fnam, O_RDWR|O_CREAT|O_EXCL, 0600);
  576.   if (fd < 0 && access(fnam, 0) >= 0 &&
  577.       (from_savefile ||
  578.        (wizard && get_check("Can't make new savefile. Overwrite old?"))))
  579.     {
  580.       (void) chmod(fnam, 0600);
  581.       fd = open(fnam, O_RDWR|O_TRUNC, 0600);
  582.     }
  583. #endif
  584.   if (fd >= 0)
  585.     {
  586.       (void) close(fd);
  587. #endif /* !ATARIST_MWC && !VMS */
  588.       /* GCC for atari st defines atarist */
  589. #if defined(atarist) || defined(ATARI_ST) || defined(THINK_C) || defined(MSDOS)
  590.       fileptr = fopen(savefile, "wb");
  591. #else
  592.       fileptr = fopen(savefile, "w");
  593. #endif
  594. #if !defined(ATARIST_MWC) && !defined(VMS)
  595.     }
  596. #endif
  597.   DEBUG(logfile = fopen("IO_LOG", "a"));
  598.   DEBUG(fprintf (logfile, "Saving data to %s\n", savefile));
  599.   if (fileptr != NULL)
  600.     {
  601.       xor_byte = 0;
  602.       wr_byte((int8u)CUR_VERSION_MAJ);
  603.       xor_byte = 0;
  604.       wr_byte((int8u)CUR_VERSION_MIN);
  605.       xor_byte = 0;
  606.       wr_byte((int8u)PATCH_LEVEL);
  607.       xor_byte = 0;
  608.       char_tmp = randint(256) - 1;
  609.       wr_byte(char_tmp);
  610.       /* Note that xor_byte is now equal to char_tmp */
  611.  
  612.       ok = sv_write();
  613.  
  614.       DEBUG(fclose (logfile));
  615.  
  616.       if (fclose(fileptr) == EOF)
  617.     ok = FALSE;
  618.     }
  619.  
  620. #ifdef MAC
  621.   macendwait ();
  622. #endif
  623.  
  624.   if (!ok)
  625.     {
  626.       if (fd >= 0)
  627.     (void) unlink(fnam);
  628.       signals();
  629.       if (fd >= 0)
  630.     (void) sprintf(temp, "Error writing to file %s", fnam);
  631.       else
  632.     (void) sprintf(temp, "Can't create new file %s", fnam);
  633.       msg_print(temp);
  634.       return FALSE;
  635.     }
  636.   else
  637.     character_saved = 1;
  638.  
  639.   turn = -1;
  640.   signals();
  641.  
  642.   return TRUE;
  643. }
  644.  
  645.  
  646. #ifdef MAC
  647. /* Wrapper to set the appropriate directory */
  648. int get_char(generate)
  649. int *generate;
  650. {
  651.   int rc, exit_flag;
  652.   int16 vrefnum;
  653.  
  654.   (void) getsavedefaults(savefile, &vrefnum);
  655.  
  656.   changedirectory(vrefnum);
  657.   rc = _get_char(generate, &exit_flag);
  658.   restoredirectory();
  659.  
  660.   if (exit_flag)
  661.     exit_game();
  662.  
  663.   return(rc);
  664. }
  665. #endif
  666.  
  667. /* Certain checks are ommitted for the wizard. -CJS- */
  668.  
  669. #ifdef MAC
  670. int _get_char(generate, exit_flag)
  671. int *generate, *exit_flag;
  672. #else
  673. int get_char(generate)
  674. int *generate;
  675. #endif
  676. {
  677.   register int i, j;
  678.   int fd, c, ok, total_count;
  679.   int32u l, age, time_saved;
  680.   vtype temp;
  681.   int16u int16u_tmp;
  682.   register cave_type *c_ptr;
  683.   register recall_type *r_ptr;
  684.   struct misc *m_ptr;
  685.   struct stats *s_ptr;
  686.   register struct flags *f_ptr;
  687.   store_type *st_ptr;
  688.   int8u char_tmp, ychar, xchar, count;
  689.   int8u version_maj, version_min, patch_level;
  690. #if defined(MSDOS) || defined(ATARI_ST)
  691.   inven_type *t_ptr;
  692. #endif
  693.  
  694. #ifdef MAC
  695.   *exit_flag = FALSE;
  696. #endif
  697.  
  698.   nosignals();
  699.   *generate = TRUE;
  700.   fd = -1;
  701.  
  702. #ifndef MAC
  703.   /* Not required for Mac, because the file name is obtained through a dialog.
  704.      There is no way for a non existnat file to be specified.  -BS-    */
  705.   if (access(savefile, 0) != 0)
  706.     {
  707.       signals();
  708.       msg_print("Savefile does not exist.");
  709.       return FALSE;    /* Don't bother with messages here. File absent. */
  710.     }
  711. #endif
  712.  
  713.   clear_screen();
  714.  
  715.   (void) sprintf(temp, "Savefile %s present. Attempting restore.", savefile);
  716.   put_buffer(temp, 23, 0);
  717.  
  718.   if (turn >= 0)
  719.     msg_print("IMPOSSIBLE! Attempt to restore while still alive!");
  720.  
  721.   /* Allow restoring a file belonging to someone else, if we can delete it. */
  722.   /* Hence first try to read without doing a chmod. */
  723.  
  724. #if defined(MAC) || defined(AMIGA)
  725.   else if ((fd = open(savefile, O_RDONLY)) < 0)
  726. #else
  727. #ifdef ATARI_ST
  728.   else if (FALSE)
  729. #else
  730.   else if ((fd = open(savefile, O_RDONLY, 0)) < 0
  731.        && (chmod(savefile, 0400) < 0 ||
  732.            (fd = open(savefile, O_RDONLY, 0)) < 0))
  733. #endif
  734. #endif
  735.     msg_print("Can't open file for reading.");
  736.   else
  737.     {
  738.       turn = -1;
  739.       ok = TRUE;
  740.  
  741.       (void) close(fd);
  742.       /* GCC for atari st defines atarist */
  743. #if defined(atarist) || defined(ATARI_ST) || defined(THINK_C) || defined(MSDOS)
  744.       fileptr = fopen(savefile, "rb");
  745. #else
  746.       fileptr = fopen(savefile, "r");
  747. #endif
  748.       if (fileptr == NULL)
  749.     goto error;
  750.  
  751. #ifdef MAC
  752.       macbeginwait ();
  753. #endif
  754.  
  755.       prt("Restoring Memory...", 0, 0);
  756.       put_qio();
  757.  
  758.       DEBUG(logfile = fopen("IO_LOG", "a"));
  759.       DEBUG(fprintf (logfile, "Reading data from %s\n", savefile));
  760.  
  761.       xor_byte = 0;
  762.       rd_byte(&version_maj);
  763.       xor_byte = 0;
  764.       rd_byte(&version_min);
  765.       xor_byte = 0;
  766.       rd_byte(&patch_level);
  767.       xor_byte = 0;
  768.       rd_byte(&xor_byte);
  769.  
  770.       /* COMPAT support savefiles from 5.0.14 to 5.0.17 */
  771.       /* support savefiles from 5.1.0 to present */
  772.       if ((version_maj != CUR_VERSION_MAJ)
  773. #if 0
  774.       /* As of version 5.4, accept savefiles even if they have higher
  775.          version numbers.  The savefile format was frozen as of version
  776.          5.2.2.  */
  777.       || (version_min > CUR_VERSION_MIN)
  778.       || (version_min == CUR_VERSION_MIN && patch_level > PATCH_LEVEL)
  779. #endif
  780.       || (version_min == 0 && patch_level < 14))
  781.     {
  782.       prt("Sorry. This savefile is from a different version of umoria.",
  783.           2, 0);
  784.       goto error;
  785.     }
  786.  
  787.       rd_short(&int16u_tmp);
  788.       while (int16u_tmp != 0xFFFF)
  789.     {
  790.       if (int16u_tmp >= MAX_CREATURES)
  791.         goto error;
  792.       r_ptr = &c_recall[int16u_tmp];
  793.       rd_long(&r_ptr->r_cmove);
  794.       rd_long(&r_ptr->r_spells);
  795.       rd_short(&r_ptr->r_kills);
  796.       rd_short(&r_ptr->r_deaths);
  797.       rd_short(&r_ptr->r_cdefense);
  798.       rd_byte(&r_ptr->r_wake);
  799.       rd_byte(&r_ptr->r_ignore);
  800.       rd_bytes(r_ptr->r_attacks, MAX_MON_NATTACK);
  801.       rd_short(&int16u_tmp);
  802.     }
  803.  
  804.       /* for save files before 5.2.2, read and ignore log_index (sic) */
  805.       if ((version_min < 2) || (version_min == 2 && patch_level < 2))
  806.     rd_short(&int16u_tmp);
  807.       rd_long(&l);
  808.  
  809.       if (l & 0x1)
  810.     find_cut = TRUE;
  811.       else
  812.     find_cut = FALSE;
  813.       if (l & 0x2)
  814.     find_examine = TRUE;
  815.       else
  816.     find_examine = FALSE;
  817.       if (l & 0x4)
  818.     find_prself = TRUE;
  819.       else
  820.     find_prself = FALSE;
  821.       if (l & 0x8)
  822.     find_bound = TRUE;
  823.       else
  824.     find_bound = FALSE;
  825.       if (l & 0x10)
  826.     prompt_carry_flag = TRUE;
  827.       else
  828.     prompt_carry_flag = FALSE;
  829.       if (l & 0x20)
  830.     rogue_like_commands = TRUE;
  831.       else
  832.     rogue_like_commands = FALSE;
  833.       if (l & 0x40)
  834.     show_weight_flag = TRUE;
  835.       else
  836.     show_weight_flag = FALSE;
  837.       if (l & 0x80)
  838.     highlight_seams = TRUE;
  839.       else
  840.     highlight_seams = FALSE;
  841.       if (l & 0x100)
  842.     find_ignore_doors = TRUE;
  843.       else
  844.     find_ignore_doors = FALSE;
  845.       /* save files before 5.2.2 don't have sound_beep_flag, set it on
  846.      for compatibility */
  847.       if ((version_min < 2) || (version_min == 2 && patch_level < 2))
  848.     sound_beep_flag = TRUE;
  849.       else if (l & 0x200)
  850.     sound_beep_flag = TRUE;
  851.       else
  852.     sound_beep_flag = FALSE;
  853.       /* save files before 5.2.2 don't have display_counts, set it on
  854.      for compatibility */
  855.       if ((version_min < 2) || (version_min == 2 && patch_level < 2))
  856.     display_counts = TRUE;
  857.       else if (l & 0x400)
  858.     display_counts = TRUE;
  859.       else
  860.     display_counts = FALSE;
  861.  
  862.       /* Don't allow resurrection of total_winner characters.  It causes
  863.      problems because the character level is out of the allowed range.  */
  864.       if (to_be_wizard && (l & 0x40000000L))
  865.     {
  866.       msg_print ("Sorry, this character is retired from moria.");
  867.       msg_print ("You can not resurrect a retired character.");
  868.     }
  869.       else if (to_be_wizard && (l & 0x80000000L)
  870.            && get_check("Resurrect a dead character?"))
  871.     l &= ~0x80000000L;
  872.       if ((l & 0x80000000L) == 0)
  873.     {
  874.       m_ptr = &py.misc;
  875.       rd_string(m_ptr->name);
  876.       rd_byte(&m_ptr->male);
  877.       rd_long((int32u *)&m_ptr->au);
  878.       rd_long((int32u *)&m_ptr->max_exp);
  879.       rd_long((int32u *)&m_ptr->exp);
  880.       rd_short(&m_ptr->exp_frac);
  881.       rd_short(&m_ptr->age);
  882.       rd_short(&m_ptr->ht);
  883.       rd_short(&m_ptr->wt);
  884.       rd_short(&m_ptr->lev);
  885.       rd_short(&m_ptr->max_dlv);
  886.       rd_short((int16u *)&m_ptr->srh);
  887.       rd_short((int16u *)&m_ptr->fos);
  888.       rd_short((int16u *)&m_ptr->bth);
  889.       rd_short((int16u *)&m_ptr->bthb);
  890.       rd_short((int16u *)&m_ptr->mana);
  891.       rd_short((int16u *)&m_ptr->mhp);
  892.       rd_short((int16u *)&m_ptr->ptohit);
  893.       rd_short((int16u *)&m_ptr->ptodam);
  894.       rd_short((int16u *)&m_ptr->pac);
  895.       rd_short((int16u *)&m_ptr->ptoac);
  896.       rd_short((int16u *)&m_ptr->dis_th);
  897.       rd_short((int16u *)&m_ptr->dis_td);
  898.       rd_short((int16u *)&m_ptr->dis_ac);
  899.       rd_short((int16u *)&m_ptr->dis_tac);
  900.       rd_short((int16u *)&m_ptr->disarm);
  901.       rd_short((int16u *)&m_ptr->save);
  902.       rd_short((int16u *)&m_ptr->sc);
  903.       rd_short((int16u *)&m_ptr->stl);
  904.       rd_byte(&m_ptr->pclass);
  905.       rd_byte(&m_ptr->prace);
  906.       rd_byte(&m_ptr->hitdie);
  907.       rd_byte(&m_ptr->expfact);
  908.       rd_short((int16u *)&m_ptr->cmana);
  909.       rd_short(&m_ptr->cmana_frac);
  910.       rd_short((int16u *)&m_ptr->chp);
  911.       rd_short(&m_ptr->chp_frac);
  912.       for (i = 0; i < 4; i++)
  913.         rd_string (m_ptr->history[i]);
  914.  
  915.       s_ptr = &py.stats;
  916.       rd_bytes(s_ptr->max_stat, 6);
  917.       rd_bytes(s_ptr->cur_stat, 6);
  918.       rd_shorts((int16u *)s_ptr->mod_stat, 6);
  919.       rd_bytes(s_ptr->use_stat, 6);
  920.  
  921.       f_ptr = &py.flags;
  922.       rd_long(&f_ptr->status);
  923.       rd_short((int16u *)&f_ptr->rest);
  924.       rd_short((int16u *)&f_ptr->blind);
  925.       rd_short((int16u *)&f_ptr->paralysis);
  926.       rd_short((int16u *)&f_ptr->confused);
  927.       rd_short((int16u *)&f_ptr->food);
  928.       rd_short((int16u *)&f_ptr->food_digested);
  929.       rd_short((int16u *)&f_ptr->protection);
  930.       rd_short((int16u *)&f_ptr->speed);
  931.       rd_short((int16u *)&f_ptr->fast);
  932.       rd_short((int16u *)&f_ptr->slow);
  933.       rd_short((int16u *)&f_ptr->afraid);
  934.       rd_short((int16u *)&f_ptr->poisoned);
  935.       rd_short((int16u *)&f_ptr->image);
  936.       rd_short((int16u *)&f_ptr->protevil);
  937.       rd_short((int16u *)&f_ptr->invuln);
  938.       rd_short((int16u *)&f_ptr->hero);
  939.       rd_short((int16u *)&f_ptr->shero);
  940.       rd_short((int16u *)&f_ptr->blessed);
  941.       rd_short((int16u *)&f_ptr->resist_heat);
  942.       rd_short((int16u *)&f_ptr->resist_cold);
  943.       rd_short((int16u *)&f_ptr->detect_inv);
  944.       rd_short((int16u *)&f_ptr->word_recall);
  945.       rd_short((int16u *)&f_ptr->see_infra);
  946.       rd_short((int16u *)&f_ptr->tim_infra);
  947.       rd_byte(&f_ptr->see_inv);
  948.       rd_byte(&f_ptr->teleport);
  949.       rd_byte(&f_ptr->free_act);
  950.       rd_byte(&f_ptr->slow_digest);
  951.       rd_byte(&f_ptr->aggravate);
  952.       rd_byte(&f_ptr->fire_resist);
  953.       rd_byte(&f_ptr->cold_resist);
  954.       rd_byte(&f_ptr->acid_resist);
  955.       rd_byte(&f_ptr->regenerate);
  956.       rd_byte(&f_ptr->lght_resist);
  957.       rd_byte(&f_ptr->ffall);
  958.       rd_byte(&f_ptr->sustain_str);
  959.       rd_byte(&f_ptr->sustain_int);
  960.       rd_byte(&f_ptr->sustain_wis);
  961.       rd_byte(&f_ptr->sustain_con);
  962.       rd_byte(&f_ptr->sustain_dex);
  963.       rd_byte(&f_ptr->sustain_chr);
  964.       rd_byte(&f_ptr->confuse_monster);
  965.       rd_byte(&f_ptr->new_spells);
  966.  
  967.       rd_short((int16u *)&missile_ctr);
  968.       rd_long((int32u *)&turn);
  969.       rd_short((int16u *)&inven_ctr);
  970.       if (inven_ctr > INVEN_WIELD)
  971.         goto error;
  972.       for (i = 0; i < inven_ctr; i++)
  973.         rd_item(&inventory[i]);
  974.       for (i = INVEN_WIELD; i < INVEN_ARRAY_SIZE; i++)
  975.         rd_item(&inventory[i]);
  976.       rd_short((int16u *)&inven_weight);
  977.       rd_short((int16u *)&equip_ctr);
  978.       rd_long(&spell_learned);
  979.       rd_long(&spell_worked);
  980.       rd_long(&spell_forgotten);
  981.       rd_bytes(spell_order, 32);
  982.       rd_bytes(object_ident, OBJECT_IDENT_SIZE);
  983.       rd_long(&randes_seed);
  984.       rd_long(&town_seed);
  985.       rd_short((int16u *)&last_msg);
  986.       for (i = 0; i < MAX_SAVE_MSG; i++)
  987.         rd_string(old_msg[i]);
  988.  
  989.       rd_short((int16u *)&panic_save);
  990.       rd_short((int16u *)&total_winner);
  991.       rd_short((int16u *)&noscore);
  992.       rd_shorts(player_hp, MAX_PLAYER_LEVEL);
  993.  
  994.       if ((version_min >= 2)
  995.           || (version_min == 1 && patch_level >= 3))
  996.         for (i = 0; i < MAX_STORES; i++)
  997.           {
  998.         st_ptr = &store[i];
  999.         rd_long((int32u *)&st_ptr->store_open);
  1000.         rd_short((int16u *)&st_ptr->insult_cur);
  1001.         rd_byte(&st_ptr->owner);
  1002.         rd_byte(&st_ptr->store_ctr);
  1003.         rd_short(&st_ptr->good_buy);
  1004.         rd_short(&st_ptr->bad_buy);
  1005.         if (st_ptr->store_ctr > STORE_INVEN_MAX)
  1006.           goto error;
  1007.         for (j = 0; j < st_ptr->store_ctr; j++)
  1008.           {
  1009.             rd_long((int32u *)&st_ptr->store_inven[j].scost);
  1010.             rd_item(&st_ptr->store_inven[j].sitem);
  1011.           }
  1012.           }
  1013.  
  1014.       if ((version_min >= 2)
  1015.           || (version_min == 1 && patch_level >= 3))
  1016.         rd_long(&time_saved);
  1017.  
  1018.       if (version_min >= 2)
  1019.         rd_string(died_from);
  1020.  
  1021.       if ((version_min >= 3)
  1022.           || (version_min == 2 && patch_level >= 2))
  1023.         rd_long ((int32u *)&max_score);
  1024.       else
  1025.         max_score = 0;
  1026.  
  1027.       if ((version_min >= 3)
  1028.           || (version_min == 2 && patch_level >= 2))
  1029.         rd_long ((int32u *)&birth_date);
  1030.       else
  1031. #ifdef MAC
  1032.         birth_date = time((time_t *)0);
  1033. #else
  1034.         birth_date = time((long *)0);
  1035. #endif
  1036.     }
  1037.       if ((c = getc(fileptr)) == EOF || (l & 0x80000000L))
  1038.     {
  1039.       if ((l & 0x80000000L) == 0)
  1040.         {
  1041.           if (!to_be_wizard || turn < 0)
  1042.         goto error;
  1043.           prt("Attempting a resurrection!", 0, 0);
  1044.           if (py.misc.chp < 0)
  1045.         {
  1046.           py.misc.chp =     0;
  1047.           py.misc.chp_frac = 0;
  1048.         }
  1049.           /* don't let him starve to death immediately */
  1050.           if (py.flags.food < 0)
  1051.         py.flags.food = 0;
  1052.           /* don't let him die of poison again immediately */
  1053.           if (py.flags.poisoned > 1)
  1054.         py.flags.poisoned = 1;
  1055.           dun_level = 0; /* Resurrect on the town level. */
  1056.           character_generated = 1;
  1057.           /* set noscore to indicate a resurrection, and don't enter
  1058.          wizard mode */
  1059.           to_be_wizard = FALSE;
  1060.           noscore |= 0x1;
  1061.         }
  1062.       else
  1063.         {
  1064.           /* Make sure that this message is seen, since it is a bit
  1065.          more interesting than the other messages.  */
  1066.           msg_print("Restoring Memory of a departed spirit...");
  1067.           turn = -1;
  1068.         }
  1069.       put_qio();
  1070.       goto closefiles;
  1071.     }
  1072.       if (ungetc(c, fileptr) == EOF)
  1073.     goto error;
  1074.  
  1075.       prt("Restoring Character...", 0, 0);
  1076.       put_qio();
  1077.  
  1078.       /* only level specific info should follow, not present for dead
  1079.          characters */
  1080.  
  1081.       rd_short((int16u *)&dun_level);
  1082.       rd_short((int16u *)&char_row);
  1083.       rd_short((int16u *)&char_col);
  1084.       rd_short((int16u *)&mon_tot_mult);
  1085.       rd_short((int16u *)&cur_height);
  1086.       rd_short((int16u *)&cur_width);
  1087.       rd_short((int16u *)&max_panel_rows);
  1088.       rd_short((int16u *)&max_panel_cols);
  1089.  
  1090.       /* read in the creature ptr info */
  1091.       rd_byte(&char_tmp);
  1092.       while (char_tmp != 0xFF)
  1093.     {
  1094.       ychar = char_tmp;
  1095.       rd_byte(&xchar);
  1096.       rd_byte(&char_tmp);
  1097.       if (xchar > MAX_WIDTH || ychar > MAX_HEIGHT)
  1098.         goto error;
  1099.       cave[ychar][xchar].cptr = char_tmp;
  1100.       rd_byte(&char_tmp);
  1101.     }
  1102.       /* read in the treasure ptr info */
  1103.       rd_byte(&char_tmp);
  1104.       while (char_tmp != 0xFF)
  1105.     {
  1106.       ychar = char_tmp;
  1107.       rd_byte(&xchar);
  1108.       rd_byte(&char_tmp);
  1109.       if (xchar > MAX_WIDTH || ychar > MAX_HEIGHT)
  1110.         goto error;
  1111.       cave[ychar][xchar].tptr = char_tmp;
  1112.       rd_byte(&char_tmp);
  1113.     }
  1114.       /* read in the rest of the cave info */
  1115.       c_ptr = &cave[0][0];
  1116.       total_count = 0;
  1117.       while (total_count != MAX_HEIGHT*MAX_WIDTH)
  1118.     {
  1119.       rd_byte(&count);
  1120.       rd_byte(&char_tmp);
  1121.       for (i = count; i > 0; i--)
  1122.         {
  1123. #ifndef ATARIST_MWC
  1124.           if (c_ptr >= &cave[MAX_HEIGHT][0])
  1125.         goto error;
  1126. #endif
  1127.           c_ptr->fval = char_tmp & 0xF;
  1128.           c_ptr->lr = (char_tmp >> 4) & 0x1;
  1129.           c_ptr->fm = (char_tmp >> 5) & 0x1;
  1130.           c_ptr->pl = (char_tmp >> 6) & 0x1;
  1131.           c_ptr->tl = (char_tmp >> 7) & 0x1;
  1132.           c_ptr++;
  1133.         }
  1134.       total_count += count;
  1135.     }
  1136.  
  1137.       rd_short((int16u *)&tcptr);
  1138.       if (tcptr > MAX_TALLOC)
  1139.     goto error;
  1140.       for (i = MIN_TRIX; i < tcptr; i++)
  1141.     rd_item(&t_list[i]);
  1142.       rd_short((int16u *)&mfptr);
  1143.       if (mfptr > MAX_MALLOC)
  1144.     goto error;
  1145.       for (i = MIN_MONIX; i < mfptr; i++)
  1146.     rd_monster(&m_list[i]);
  1147.  
  1148. #if defined(MSDOS) || defined(ATARI_ST)
  1149.       /* change walls and floors to graphic symbols */
  1150.       t_ptr = &t_list[tcptr - 1];
  1151.       for (i = tcptr - 1; i >= MIN_TRIX; i--)
  1152.     {
  1153. #ifdef MSDOS
  1154.       if (t_ptr->tchar == '#')
  1155.         t_ptr->tchar = wallsym;
  1156. #endif
  1157. #ifdef ATARI_ST
  1158.       if (t_ptr->tchar == '#')
  1159.         t_ptr->tchar = (unsigned char) 240;
  1160. #endif
  1161.       t_ptr--;
  1162.     }
  1163. #endif
  1164.  
  1165.       *generate = FALSE;  /* We have restored a cave - no need to generate. */
  1166.  
  1167.       if ((version_min == 1 && patch_level < 3)
  1168.       || (version_min == 0))
  1169.     for (i = 0; i < MAX_STORES; i++)
  1170.       {
  1171.         st_ptr = &store[i];
  1172.         rd_long((int32u *)&st_ptr->store_open);
  1173.         rd_short((int16u *)&st_ptr->insult_cur);
  1174.         rd_byte(&st_ptr->owner);
  1175.         rd_byte(&st_ptr->store_ctr);
  1176.         rd_short(&st_ptr->good_buy);
  1177.         rd_short(&st_ptr->bad_buy);
  1178.         if (st_ptr->store_ctr > STORE_INVEN_MAX)
  1179.           goto error;
  1180.         for (j = 0; j < st_ptr->store_ctr; j++)
  1181.           {
  1182.         rd_long((int32u *)&st_ptr->store_inven[j].scost);
  1183.         rd_item(&st_ptr->store_inven[j].sitem);
  1184.           }
  1185.       }
  1186.  
  1187.       /* read the time that the file was saved */
  1188.       if (version_min == 0 && patch_level < 16)
  1189.     time_saved = 0; /* no time in file, clear to zero */
  1190.       else if (version_min == 1 && patch_level < 3)
  1191.     rd_long(&time_saved);
  1192.  
  1193.       if (ferror(fileptr))
  1194.     goto error;
  1195.  
  1196.       if (turn < 0)
  1197.       error:
  1198.     ok = FALSE;    /* Assume bad data. */
  1199.       else
  1200.     {
  1201.       /* don't overwrite the killed by string if character is dead */
  1202.       if (py.misc.chp >= 0)
  1203.         (void) strcpy(died_from, "(alive and well)");
  1204.       character_generated = 1;
  1205.     }
  1206.  
  1207.     closefiles:
  1208.  
  1209.       DEBUG(fclose (logfile));
  1210.  
  1211.       if (fileptr != NULL)
  1212.     {
  1213.       if (fclose(fileptr) < 0)
  1214.         ok = FALSE;
  1215.     }
  1216.       if (fd >= 0)
  1217.     (void) close(fd);
  1218.  
  1219. #ifdef MAC
  1220.       macendwait ();
  1221. #endif
  1222.  
  1223.       if (!ok)
  1224.     msg_print("Error during reading of file.");
  1225.       else
  1226.     {
  1227.       /* let the user overwrite the old savefile when save/quit */
  1228.       from_savefile = 1;
  1229.  
  1230.       signals();
  1231.  
  1232.       if (panic_save == 1)
  1233.         {
  1234.           (void) sprintf(temp, "This game is from a panic save.  \
  1235. Score will not be added to scoreboard.");
  1236.           msg_print (temp);
  1237.         }
  1238.       else if ((!noscore & 0x04) && duplicate_character ())
  1239.         {
  1240.           (void) sprintf (temp, "This character is already on the \
  1241. scoreboard; it will not be scored again.");
  1242.           msg_print (temp);
  1243.           noscore |= 0x4;
  1244.         }
  1245.  
  1246.       if (turn >= 0)
  1247.         {    /* Only if a full restoration. */
  1248.           weapon_heavy = FALSE;
  1249.           pack_heavy = 0;
  1250.           check_strength();
  1251.  
  1252.           /* rotate store inventory, depending on how old the save file */
  1253.           /* is foreach day old (rounded up), call store_maint */
  1254.           /* calculate age in seconds */
  1255. #ifdef MAC
  1256.           start_time = time((time_t *)0);
  1257. #else
  1258.           start_time = time((long *)0);
  1259. #endif
  1260.           /* check for reasonable values of time here ... */
  1261.           if (start_time < time_saved)
  1262.         age = 0;
  1263.           else
  1264.         age = start_time - time_saved;
  1265.  
  1266.           age = (age + 43200L) / 86400L;  /* age in days */
  1267.           if (age > 10) age = 10; /* in case savefile is very old */
  1268.           for (i = 0; i < age; i++)
  1269.         store_maint();
  1270.         }
  1271.  
  1272.       if (noscore)
  1273.         msg_print("This save file cannot be used to get on the score board.");
  1274.  
  1275.       if (version_maj != CUR_VERSION_MAJ
  1276.           || version_min != CUR_VERSION_MIN)
  1277.         {
  1278.           (void) sprintf(temp,
  1279.                  "Save file version %d.%d %s on game version %d.%d.",
  1280.                  version_maj, version_min,
  1281.                  version_min <= CUR_VERSION_MIN
  1282.                  ? "accepted" : "risky" ,
  1283.                  CUR_VERSION_MAJ, CUR_VERSION_MIN);
  1284.           msg_print(temp);
  1285.         }
  1286.  
  1287.       if (turn >= 0)
  1288.         return TRUE;
  1289.       else
  1290.         return FALSE;    /* Only restored options and monster memory. */
  1291.     }
  1292.     }
  1293.   turn = -1;
  1294.   prt("Please try again without that savefile.", 1, 0);
  1295.   signals();
  1296. #ifdef MAC
  1297.   *exit_flag = TRUE;
  1298. #else
  1299.   exit_game();
  1300. #endif
  1301.  
  1302.   return FALSE;    /* not reached, unless on mac */
  1303. }
  1304.  
  1305. static void wr_byte(c)
  1306. int8u c;
  1307. {
  1308.   xor_byte ^= c;
  1309.   (void) putc((int)xor_byte, fileptr);
  1310.   DEBUG(fprintf (logfile, "BYTE:  %02X = %d\n", (int) xor_byte, (int) c));
  1311. }
  1312.  
  1313. static void wr_short(s)
  1314. int16u s;
  1315. {
  1316.   xor_byte ^= (s & 0xFF);
  1317.   (void) putc((int)xor_byte, fileptr);
  1318.   DEBUG(fprintf (logfile, "SHORT: %02X", (int) xor_byte));
  1319.   xor_byte ^= ((s >> 8) & 0xFF);
  1320.   (void) putc((int)xor_byte, fileptr);
  1321.   DEBUG(fprintf (logfile, " %02X = %d\n", (int) xor_byte, (int) s));
  1322. }
  1323.  
  1324. static void wr_long(l)
  1325. register int32u l;
  1326. {
  1327.   xor_byte ^= (l & 0xFF);
  1328.   (void) putc((int)xor_byte, fileptr);
  1329.   DEBUG(fprintf (logfile, "LONG:  %02X", (int) xor_byte));
  1330.   xor_byte ^= ((l >> 8) & 0xFF);
  1331.   (void) putc((int)xor_byte, fileptr);
  1332.   DEBUG(fprintf (logfile, " %02X", (int) xor_byte));
  1333.   xor_byte ^= ((l >> 16) & 0xFF);
  1334.   (void) putc((int)xor_byte, fileptr);
  1335.   DEBUG(fprintf (logfile, " %02X", (int) xor_byte));
  1336.   xor_byte ^= ((l >> 24) & 0xFF);
  1337.   (void) putc((int)xor_byte, fileptr);
  1338.   DEBUG(fprintf (logfile, " %02X = %ld\n", (int) xor_byte, (long) l));
  1339. }
  1340.  
  1341. static void wr_bytes(c, count)
  1342. int8u *c;
  1343. register int count;
  1344. {
  1345.   register int i;
  1346.   register int8u *ptr;
  1347.  
  1348.   DEBUG(fprintf (logfile, "%d BYTES:", count));
  1349.   ptr = c;
  1350.   for (i = 0; i < count; i++)
  1351.     {
  1352.       xor_byte ^= *ptr++;
  1353.       (void) putc((int)xor_byte, fileptr);
  1354.       DEBUG(fprintf (logfile, "  %02X = %d", (int) xor_byte,
  1355.              (int) (ptr[-1])));
  1356.     }
  1357.   DEBUG(fprintf (logfile, "\n"));
  1358. }
  1359.  
  1360. static void wr_string(str)
  1361. register char *str;
  1362. {
  1363.   DEBUG(char *s = str);
  1364.   DEBUG(fprintf (logfile, "STRING:"));
  1365.   while (*str != '\0')
  1366.     {
  1367.       xor_byte ^= *str++;
  1368.       (void) putc((int)xor_byte, fileptr);
  1369.       DEBUG(fprintf (logfile, " %02X", (int) xor_byte));
  1370.     }
  1371.   xor_byte ^= *str;
  1372.   (void) putc((int)xor_byte, fileptr);
  1373.   DEBUG(fprintf (logfile, " %02X = \"%s\"\n", (int) xor_byte, s));
  1374. }
  1375.  
  1376. static void wr_shorts(s, count)
  1377. int16u *s;
  1378. register int count;
  1379. {
  1380.   register int i;
  1381.   register int16u *sptr;
  1382.  
  1383.   DEBUG(fprintf (logfile, "%d SHORTS:", count));
  1384.   sptr = s;
  1385.   for (i = 0; i < count; i++)
  1386.     {
  1387.       xor_byte ^= (*sptr & 0xFF);
  1388.       (void) putc((int)xor_byte, fileptr);
  1389.       DEBUG(fprintf (logfile, "  %02X", (int) xor_byte));
  1390.       xor_byte ^= ((*sptr++ >> 8) & 0xFF);
  1391.       (void) putc((int)xor_byte, fileptr);
  1392.       DEBUG(fprintf (logfile, " %02X = %d", (int) xor_byte, (int) sptr[-1]));
  1393.     }
  1394.   DEBUG(fprintf (logfile, "\n"));
  1395. }
  1396.  
  1397. static void wr_item(item)
  1398. register inven_type *item;
  1399. {
  1400.   DEBUG(fprintf (logfile, "ITEM:\n"));
  1401.   wr_short(item->index);
  1402.   wr_byte(item->name2);
  1403.   wr_string(item->inscrip);
  1404.   wr_long(item->flags);
  1405.   wr_byte(item->tval);
  1406.   wr_byte(item->tchar);
  1407.   wr_short((int16u)item->p1);
  1408.   wr_long((int32u)item->cost);
  1409.   wr_byte(item->subval);
  1410.   wr_byte(item->number);
  1411.   wr_short(item->weight);
  1412.   wr_short((int16u)item->tohit);
  1413.   wr_short((int16u)item->todam);
  1414.   wr_short((int16u)item->ac);
  1415.   wr_short((int16u)item->toac);
  1416.   wr_bytes(item->damage, 2);
  1417.   wr_byte(item->level);
  1418.   wr_byte(item->ident);
  1419. }
  1420.  
  1421. static void wr_monster(mon)
  1422. register monster_type *mon;
  1423. {
  1424.   DEBUG(fprintf (logfile, "MONSTER:\n"));
  1425.   wr_short((int16u)mon->hp);
  1426.   wr_short((int16u)mon->csleep);
  1427.   wr_short((int16u)mon->cspeed);
  1428.   wr_short(mon->mptr);
  1429.   wr_byte(mon->fy);
  1430.   wr_byte(mon->fx);
  1431.   wr_byte(mon->cdis);
  1432.   wr_byte(mon->ml);
  1433.   wr_byte(mon->stunned);
  1434.   wr_byte(mon->confused);
  1435. }
  1436.  
  1437. static void rd_byte(ptr)
  1438. int8u *ptr;
  1439. {
  1440.   int8u c;
  1441.  
  1442.   c = getc(fileptr) & 0xFF;
  1443.   *ptr = c ^ xor_byte;
  1444.   xor_byte = c;
  1445.   DEBUG(fprintf (logfile, "BYTE:  %02X = %d\n", (int) c, (int) *ptr));
  1446. }
  1447.  
  1448. static void rd_short(ptr)
  1449. int16u *ptr;
  1450. {
  1451.   int8u c;
  1452.   int16u s;
  1453.  
  1454.   c = (getc(fileptr) & 0xFF);
  1455.   s = c ^ xor_byte;
  1456.   xor_byte = (getc(fileptr) & 0xFF);
  1457.   s |= (int16u)(c ^ xor_byte) << 8;
  1458.   *ptr = s;
  1459.   DEBUG(fprintf (logfile, "SHORT: %02X %02X = %d\n", (int) c, (int) xor_byte,\
  1460.          (int) s));
  1461. }
  1462.  
  1463. static void rd_long(ptr)
  1464. int32u *ptr;
  1465. {
  1466.   register int32u l;
  1467.   register int8u c;
  1468.  
  1469.   c = (getc(fileptr) & 0xFF);
  1470.   l = c ^ xor_byte;
  1471.   xor_byte = (getc(fileptr) & 0xFF);
  1472.   l |= (int32u)(c ^ xor_byte) << 8;
  1473.   DEBUG(fprintf (logfile, "LONG:  %02X %02X ", (int) c, (int) xor_byte));
  1474.   c = (getc(fileptr) & 0xFF);
  1475.   l |= (int32u)(c ^ xor_byte) << 16;
  1476.   xor_byte = (getc(fileptr) & 0xFF);
  1477.   l |= (int32u)(c ^ xor_byte) << 24;
  1478.   *ptr = l;
  1479.   DEBUG(fprintf (logfile, "%02X %02X = %ld\n", (int) c, (int) xor_byte,\
  1480.          (long) l));
  1481. }
  1482.  
  1483. static void rd_bytes(ch_ptr, count)
  1484. int8u *ch_ptr;
  1485. register int count;
  1486. {
  1487.   register int i;
  1488.   register int8u *ptr;
  1489.   register int8u c;
  1490.  
  1491.   DEBUG(fprintf (logfile, "%d BYTES:", count));
  1492.   ptr = ch_ptr;
  1493.   for (i = 0; i < count; i++)
  1494.     {
  1495.       c = (getc(fileptr) & 0xFF);
  1496.       *ptr++ = c ^ xor_byte;
  1497.       xor_byte = c;
  1498.       DEBUG(fprintf (logfile, "  %02X = %d", (int) c, (int) ptr[-1]));
  1499.     }
  1500.   DEBUG(fprintf (logfile, "\n"));
  1501. }
  1502.  
  1503. static void rd_string(str)
  1504. char *str;
  1505. {
  1506.   register int8u c;
  1507.  
  1508.   DEBUG(char *s = str);
  1509.   DEBUG(fprintf (logfile, "STRING: "));
  1510.   do
  1511.     {
  1512.       c = (getc(fileptr) & 0xFF);
  1513.       *str = c ^ xor_byte;
  1514.       xor_byte = c;
  1515.       DEBUG(fprintf (logfile, "%02X ", (int) c));
  1516.     }
  1517.   while (*str++ != '\0');
  1518.   DEBUG(fprintf (logfile, "= \"%s\"\n", s));
  1519. }
  1520.  
  1521. static void rd_shorts(ptr, count)
  1522. int16u *ptr;
  1523. register int count;
  1524. {
  1525.   register int i;
  1526.   register int16u *sptr;
  1527.   register int16u s;
  1528.   int8u c;
  1529.  
  1530.   DEBUG(fprintf (logfile, "%d SHORTS:", count));
  1531.   sptr = ptr;
  1532.   for (i = 0; i < count; i++)
  1533.     {
  1534.       c = (getc(fileptr) & 0xFF);
  1535.       s = c ^ xor_byte;
  1536.       xor_byte = (getc(fileptr) & 0xFF);
  1537.       s |= (int16u)(c ^ xor_byte) << 8;
  1538.       *sptr++ = s;
  1539.       DEBUG(fprintf (logfile, "  %02X %02X = %d", (int) c, (int) xor_byte,\
  1540.              (int) s));
  1541.     }
  1542.   DEBUG(fprintf (logfile, "\n"));
  1543. }
  1544.  
  1545. static void rd_item(item)
  1546. register inven_type *item;
  1547. {
  1548.   DEBUG(fprintf (logfile, "ITEM:\n"));
  1549.   rd_short(&item->index);
  1550.   rd_byte(&item->name2);
  1551.   rd_string(item->inscrip);
  1552.   rd_long(&item->flags);
  1553.   rd_byte(&item->tval);
  1554.   rd_byte(&item->tchar);
  1555.   rd_short((int16u *)&item->p1);
  1556.   rd_long((int32u *)&item->cost);
  1557.   rd_byte(&item->subval);
  1558.   rd_byte(&item->number);
  1559.   rd_short(&item->weight);
  1560.   rd_short((int16u *)&item->tohit);
  1561.   rd_short((int16u *)&item->todam);
  1562.   rd_short((int16u *)&item->ac);
  1563.   rd_short((int16u *)&item->toac);
  1564.   rd_bytes(item->damage, 2);
  1565.   rd_byte(&item->level);
  1566.   rd_byte(&item->ident);
  1567. }
  1568.  
  1569. static void rd_monster(mon)
  1570. register monster_type *mon;
  1571. {
  1572.   DEBUG(fprintf (logfile, "MONSTER:\n"));
  1573.   rd_short((int16u *)&mon->hp);
  1574.   rd_short((int16u *)&mon->csleep);
  1575.   rd_short((int16u *)&mon->cspeed);
  1576.   rd_short(&mon->mptr);
  1577.   rd_byte(&mon->fy);
  1578.   rd_byte(&mon->fx);
  1579.   rd_byte(&mon->cdis);
  1580.   rd_byte(&mon->ml);
  1581.   rd_byte(&mon->stunned);
  1582.   rd_byte(&mon->confused);
  1583. }
  1584.  
  1585. /* functions called from death.c to implement the score file */
  1586.  
  1587. /* set the local fileptr to the scorefile fileptr */
  1588. void set_fileptr(file)
  1589. FILE *file;
  1590. {
  1591.   fileptr = file;
  1592. }
  1593.  
  1594. void wr_highscore(score)
  1595. high_scores *score;
  1596. {
  1597.   DEBUG(logfile = fopen ("IO_LOG", "a"));
  1598.   DEBUG(fprintf (logfile, "Saving score:\n"));
  1599.   /* Save the encryption byte for robustness.  */
  1600.   wr_byte(xor_byte);
  1601.  
  1602.   wr_long((int32u) score->points);
  1603.   wr_long((int32u) score->birth_date);
  1604.   wr_short((int16u) score->uid);
  1605.   wr_short((int16u) score->mhp);
  1606.   wr_short((int16u) score->chp);
  1607.   wr_byte(score->dun_level);
  1608.   wr_byte(score->lev);
  1609.   wr_byte(score->max_dlv);
  1610.   wr_byte(score->sex);
  1611.   wr_byte(score->race);
  1612.   wr_byte(score->class);
  1613.   wr_bytes((int8u *)score->name, PLAYER_NAME_SIZE);
  1614.   wr_bytes((int8u *)score->died_from, 25);
  1615.   DEBUG(fclose (logfile));
  1616. }
  1617.  
  1618. void rd_highscore(score)
  1619. high_scores *score;
  1620. {
  1621.   DEBUG(logfile = fopen ("IO_LOG", "a"));
  1622.   DEBUG(fprintf (logfile, "Reading score:\n"));
  1623.   /* Read the encryption byte.  */
  1624.   rd_byte (&xor_byte);
  1625.  
  1626.   rd_long((int32u *)&score->points);
  1627.   rd_long((int32u *)&score->birth_date);
  1628.   rd_short((int16u *)&score->uid);
  1629.   rd_short((int16u *)&score->mhp);
  1630.   rd_short((int16u *)&score->chp);
  1631.   rd_byte(&score->dun_level);
  1632.   rd_byte(&score->lev);
  1633.   rd_byte(&score->max_dlv);
  1634.   rd_byte(&score->sex);
  1635.   rd_byte(&score->race);
  1636.   rd_byte(&score->class);
  1637.   rd_bytes((int8u *)score->name, PLAYER_NAME_SIZE);
  1638.   rd_bytes((int8u *)score->died_from, 25);
  1639.   DEBUG(fclose (logfile));
  1640. }
  1641.